package com.hhd.flow.engine.cmd.impl;

import com.alibaba.fastjson.JSONObject;
import com.hhd.flow.engine.utils.CommonUtils;
import com.hhd.flow.engine.utils.FlowUtils;
import com.hhd.flow.engine.vo.ApproveType;
import com.hhd.flow.engine.vo.CommentType;
import com.hhd.flow.engine.vo.FlowModel;
import com.hhd.flow.engine.vo.UserManualSelect;
import com.hhd.flow.entity.*;
import com.hhd.flow.exception.FlowException;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import org.springframework.beans.BeanUtils;

@Setter
@Getter
@SuperBuilder(toBuilder = true)
public class EndCommand extends BaseCommand<Void> {
    private String flowUserTaskId;//待审批的用户任务
    private UserManualSelect userManualSelect; //手动指定的审批人
    private JSONObject model; //业务单据的数据
    private String comment; //用户的评论
    private String userSign; //用户的手签
    private String attachmentIds; //附件列表
    private ApproveType approveType;//用户的处理类型
    private String commentInfo; //评论其他信息(用来给前端做特殊展示, json格式)

    //下面是运转过程中产生的数据
    private FlowUserTask flowUserTask;
    private FlowComment flowComment;
    private FlowProcessInstance processInstance;
    private FlowProcessInstanceHistory flowProcessInstanceHistory;
    private FlowModel flowModel;

    @Override
    public Void execute() {
        loadFlowUserTask();

        createComment();

        publishFlowUserTaskBeforeEndEvent();

        doEndUserTask();

        publishFlowUserTaskAfterEndEvent();

        forFlowUserDone(flowUserTask.getFormId());

        return null;
    }

    private void publishFlowUserTaskAfterEndEvent() {
        publishFlowUserTaskAfterEndEvent(this);
    }

    private void doEndUserTask() {
        createHistory();

        getEngine().getFlowTaskService().lambdaUpdate()
                .eq(FlowTask::getProcessInstanceId, flowUserTask.getProcessInstanceId())
                .remove();

        getEngine().getFlowUserTaskService().lambdaUpdate()
                .eq(FlowUserTask::getProcessInstanceId, flowUserTask.getProcessInstanceId())
                .remove();

        getEngine().getFlowGatewayExecutionService().lambdaUpdate()
                .eq(FlowGatewayExecution::getProcessInstanceId, flowUserTask.getProcessInstanceId())
                .remove();

        removeProcessInstanceToHistory();

        savePath();
    }

    private void savePath() {
        FlowPath flowPath = loadFlowPathByProcessInstance(processInstance);
        flowPath.setEndId(flowUserTask.getTaskDefinitionId());
        savePath(flowPath);
    }

    private void removeProcessInstanceToHistory() {
        processInstance = getEngine().getFlowProcessInstanceService().getById(flowUserTask.getProcessInstanceId());
        getEngine().getFlowProcessInstanceService().removeById(processInstance.getId());
        flowProcessInstanceHistory = FlowUtils.createFlowProcessInstanceHistory(processInstance, CommentType.end, false);
        getEngine().getFlowProcessInstanceHistoryService().save(flowProcessInstanceHistory);
        BeanUtils.copyProperties(flowProcessInstanceHistory, processInstance);
    }

    private void createHistory() {
        FlowUtils.endFlowUserTask(flowUserTask, CommentType.end, userSign);
        FlowUserTaskHistory his = CommonUtils.copyTo(flowUserTask, FlowUserTaskHistory.class);
        getEngine().getFlowUserTaskHistoryService().save(his);
        getEngine().getFlowUserTaskService().removeById(flowUserTaskId);
    }

    private void publishFlowUserTaskBeforeEndEvent() {
        publishFlowUserTaskBeforeEndEvent(this);
    }

    private void createComment() {
        flowComment = FlowUtils.createComment(this.flowUserTask, comment, userSign, attachmentIds, approveType, commentInfo);
        flowComment.setCommentType(CommentType.end.name());
        flowComment.setCommentTypeName(CommentType.end.getTitle());
        getEngine().getFlowCommentService().save(flowComment);
    }

    private void loadFlowUserTask() {
        flowUserTask = getEngine().getFlowUserTaskService().getById(flowUserTaskId);
        CommonUtils.isEmptyThrow(flowUserTask, new FlowException("没有找到用户任务: " + flowUserTaskId + "请刷新页面后重试"));
        if (flowUserTask.getNotify()) {
            throw new FlowException("知会节点不支持结束流程操作");
        }
        flowModel = loadFlowModelByProcessInstanceId(flowUserTask.getProcessInstanceId());
        processInstance = getEngine().getFlowProcessInstanceService().getById(flowUserTask.getProcessInstanceId());
    }
}
